var CONFIG = {
	'APP_NAME': 'Wechat Searcher',
	'AUTHOR': 'pysche[at]ipbfans.org'
};

var path = require('path'),
	express = require('express'),
	app = express(),
	events = require('events'),
	zlib = require('zlib'),
	DOMParser = require('xmldom').DOMParser,
	port = 40000,
	ip = '';

if (process.env.PORT) {
	port = process.env.PORT;
}

//	OpenShift支持	START
if (process.env.OPENSHIFT_NODEJS_PORT) {
	port = process.env.OPENSHIFT_NODEJS_PORT;
}

if (process.env.OPENSHIFT_NODEJS_IP) {
	ip = process.env.OPENSHIFT_NODEJS_IP;
}
//	OpenShift支持	END

var colors = require('colors'),
	jsdom = require('jsdom').jsdom,
	http = require('http'),
	fs = require('fs'),
	jquery = fs.readFileSync('./jquery.js', 'utf-8');	

app.use(express.logger());
app.use(express.bodyParser());
app.use(express.cookieParser('secret'));
app.use(express.session({
	'secret': 'pdbang'
}));
app.use(app.router);

/**
 *	这里从搜狗拿到的是XML，还得解析
 *
 */
function fetchArticles(openid, page, callback) {
	var time = Date.parse(new Date());
	var options = {
		'hostname': 'weixin.sogou.com',
		'port': 80,
		'path': '/gzhjs?cb=sogou.weixin.gzhcb&openid='+openid+'&page='+page+'&t='+time,
		'method': 'GET'
	};

	var req = http.request(options, function (res) {
		var html = '';
		res.setEncoding('utf8');
		res.on('data', function (chunk) {
			html += chunk;
		});
		res.on('end', function () {
			var data = {};
			var rows = [];

			try {
				var tmp = html.split("\n");
				var jsonStr = tmp[1].trim();
				jsonStr = jsonStr.substr(19);
				jsonStr = jsonStr.substr(0, jsonStr.length-1);

				data = JSON.parse(jsonStr);

				var items = data.items;
				var page = data.page;
				var total = data.totalPage;

				if (items && items.length>0) {
					var parseXML = function (data) {
							var xml;
							tmp = new DOMParser();
							xml = tmp.parseFromString(data, "text/xml");
							return xml.documentElement;						
						},
						gt = function (e, n) {
							var a = e.getElementsByTagName(n);
							if(a && a.length>0){
								return a[0];
							}
							return null;							
						},
						formatDate = function (str, b) {
							var d = new Date();
							d.setTime(str*1000);
							var day = d.getDate();
							var month = d.getMonth()+1;
							var year = d.getFullYear();
							var f = function (n) {
								return n>9 ? n : ('0'+n);
							};

							var date = year+'-'+f(month)+'-'+f(day);

							if (b) {
								var hour = d.getHours();
								var min = d.getMinutes();

								date = date+' '+f(hour)+':'+f(min);
							}

							return date;
						},
						tagtext = function (obj) {
							if(!obj || obj.firstChild == null)
								return "";
							return obj.firstChild.nodeValue;			
						},
						xml2obj = function (xml) {
							var obj = {};
							if(xml){
								var doc = parseXML(xml);
								if(doc && gt(doc,'display')){
									var tplid = gt(doc, 'tplid');
									var row = gt(doc, 'display');
									obj.url = tagtext(gt(row, 'url'));
									obj.title = tagtext(gt(row, 'title'));
									obj.imglink = tagtext(gt(row, 'imglink'));
									obj.lastModified = tagtext(gt(row, 'lastModified'));
									obj.date = formatDate(obj.lastModified);
									obj.sourcename = tagtext(gt(row, 'sourcename'));
									obj.content = tagtext(gt(row, 'content'));
									obj.isV = tagtext(gt(row, 'isV'));
									obj.classid = tagtext(gt(row, 'classid'));
								}
							}		

							return obj;				
						};

					for (var i=0;i<items.length;i++) {
						var obj = xml2obj(items[i]);
						if (obj) {
							rows.push(obj);
						}
					}
				}
			} catch (e) {
				console.log(('articles exception: '+e.message).red);
			}

			callback(rows);
		});
	});

	req.on('error', function (e) {
		console.log(('articles sogou failed: '+e.message).red);
	});

	req.write('data\n');
	req.write('data\n');
	req.end();

	console.log(('starting articles ['+openid+'] ['+page+']').green);
};

/**
 *	提取公众号详情
 *
 */
function fetchDetail(openid, callback) {
	var options = {
		'hostname': 'weixin.sogou.com',
		'port': 80,
		'path': '/gzh?openid='+openid,
		'method': 'GET'
	};

	var req = http.request(options, function (res) {
		var html = '';
		res.setEncoding('utf8');
		res.on('data', function (chunk) {
			html += chunk;
		});
		res.on('end', function () {
			jsdom.env({
				'html': html,
				'src': [jquery],
				'done': function (errors, window) {
					var $ = window.$;

					var results = $('div.results').eq(0);
					var wxid = results.find('div.wx-rb.wx-rb2').eq(0).find('div.txt-box').eq(0).find('span').eq(0).text().replace('微信号：', '');
					var wxname = results.find('h3#weixinname').eq(0).text();
					var avatar = results.find('div.wx-rb.wx-rb2 div.img-box img').eq(0).attr('src');
					var intro = results.find('div.s-p2').eq(0).find('span.sp-txt').eq(0).text();
					var qrcode = results.find('div.v-box img').eq(0).attr('src');
					var authinfo = results.find('div.s-p2').eq(1).find('span.sp-txt').eq(0).text();					
					var wechat = {
						wxid: wxid,
						wxname: wxname,
						avatar: avatar,
						intro: intro,
						qrcode: qrcode,
						authinfo: authinfo
					};
					callback({
						'results': wechat
					});
					window.close();
				}
			});
		});
	});

	req.on('error', function (e) {
		console.log(('detail sogou failed: '+e.message).red);
	});

	req.write('data\n');
	req.write('data\n');
	req.end();

	console.log(('starting detail ['+openid+']').green);
};

/**
 *	提取微信公众号列表
 *
 */
function fetchList(word, page, callback) {
	var time = Date.parse(new Date());
	var options = {
		'hostname': 'weixin.sogou.com',
		'port': 80,
		'path': '/weixin?page='+page+'&query='+encodeURIComponent(word)+'&_asf=www.sogou.com&_ast='+time+'&w=01019900&p=40040100&ie=utf8&type=1',
		'method': 'GET'
	};
	
	var req = http.request(options, function (res) {
		var html = '';
		res.setEncoding('utf8');
		res.on('data', function (chunk) {
			html += chunk;
		});
		res.on('end', function () {
			jsdom.env({
				'html': html,
				'src': [jquery],
				'done': function (errors, window) {
					var $ = window.$;

					var results = $('div.results').eq(0);
					var pagerc = $('#pagebar_container');
					var rows = [];
					var pager = {};

					results.find('a.wx-rb').each(function () {
						var $this = $(this);
						var wechat = {};
						var txtbox = $this.find('div.txt-box').eq(0);

						wechat.openid = $this.attr('href').toString().replace('/gzh?openid=', '');
						wechat.wxid = txtbox.find('h4').eq(0).text().replace('微信号：', '');
						wechat.wxname = txtbox.find('h3').eq(0).text().trim();
						wechat.intro = txtbox.find('span.sp-txt').eq(0).text().trim();
						wechat.authinfo = txtbox.find('span.sp-txt').eq(1).text().trim();
						wechat.qrcode = $this.find('div.v-box img').eq(0).attr('src');
						wechat.avatar = $this.find('div.img-box img').eq(0).attr('src');

						rows.push(wechat);
					});

					pager.total = parseInt(pagerc.find('resnum').eq(0).text());
					pager.page = parseInt(pagerc.find('span').eq(0).text());

					callback({
						'results': rows,
						'pager': pager
					});	

					//	释放window资源
					window.close();
				}
			});	//	--jsdom.env
		});	//	--res.on('end')
	});

	req.on('error', function (e) {
		console.log(('fetch sogou failed: '+e.message).red);
	});

	req.write('data\n');
	req.write('data\n');
	req.end();

	console.log(('starting fetch ['+word+'], page ['+page+']').green);
};

function output(req, res, result, jsonpCallback) {

	//	do output
	res.status(200);
	if (jsonpCallback) {
		var output = jsonpCallback+'('+JSON.stringify(result).trim()+')';
		var jlength = output.length;
		var headers = {
			'X-Powered-By': 'pdbang',
			'Content-Type': 'application/javascript; charset=utf-8',
			'Content-Length': jlength
		};
	} else {
		var output = JSON.stringify(result).trim();
		var jlength = output.length;
		var headers = {
			'X-Powered-By': 'pdbang',
			'Content-Type': 'application/json; charset=utf-8',
			'Content-Length': jlength
		};
	}

	var ae = req.headers['accept-encoding'] || '';
	var gzip = false;

	if (jlength>100 && ae.match(/\bgzip\b/)) {
		gzip = true;

		try {
			zlib.gzip(output, function (err, buffer) {
				headers['Content-Encoding'] = 'gzip';
				headers['Content-Length'] = buffer.length;

				res.set(headers);
				res.send(200, buffer);
			});
		} catch (e) {
			res.set(headers);
			res.send(200, output);
		}
	} else {
		res.set(headers);
		res.send(200, output);
	}	
};

/**
 *	文章列表
 */
app.all('/articles', function (req, res) {
	var result = {
		'ret': 0,
		'data': {}
	};
	var page = 1;

	var jsonpCallback = '';
	if (typeof req.body['callback'] != 'undefined') {
		jsonpCallback = req.body['callback'];
	} else if (typeof req.param('callback') != 'undefined') {
		jsonpCallback = req.param('callback');
	}

	var openid = '';
	if (typeof req.body['openid'] != 'undefined') {
		openid = req.body['openid'];
	} else if (typeof req.param('openid') != 'undefined') {
		openid = req.param('openid');
	}

	if (typeof req.body['page'] != 'undefined') {
		page = parseInt(req.body['page']);
	} else if (typeof req.param('page') != 'undefined') {
		page = parseInt(req.param('page'));
	}

	if (typeof page=='undefined' || isNaN(page)) {
		page = 1;
	} else if (page<=0) {
		page = 1;
	}

	if (openid=='') {
		result.ret = -1;
		delete result.data;

		output(req, res, result, jsonpCallback);
	} else {
		fetchArticles(openid, page, function (data) {
			result.data = data;

			output(req, res, result, jsonpCallback);
		});
	}
});

/**
 *	公众号详情
 *	这些信息其实在列表里面已经可以拿到了
 */
app.all('/detail', function (req, res) {
	var result = {
		'ret': 0,
		'data': {}
	};

	var jsonpCallback = '';
	if (typeof req.body['callback'] != 'undefined') {
		jsonpCallback = req.body['callback'];
	} else if (typeof req.param('callback') != 'undefined') {
		jsonpCallback = req.param('callback');
	}

	var openid = '';
	if (typeof req.body['openid'] != 'undefined') {
		openid = req.body['openid'];
	} else if (typeof req.param('openid') != 'undefined') {
		openid = req.param('openid');
	}

	if (openid=='') {
		result.ret = -1;
		delete result.data;

		output(req, res, result, jsonpCallback);
	} else {
		fetchDetail(openid, function (data) {
			result.data = data;

			output(req, res, result, jsonpCallback);
		});
	}
});

/**
 *	根据关键字查找公众号
 */
app.all('/search', function (req, res) {
	var result = {
			'ret': 0,
			'data': {}
		},
		page = 1,
		word = '';

	//	jsonP支持
	var jsonpCallback = '';
	if (typeof req.body['callback'] != 'undefined') {
		jsonpCallback = req.body['callback'];
	} else if (typeof req.param('callback') != 'undefined') {
		jsonpCallback = req.param('callback');
	}

	if (typeof req.body['page'] != 'undefined') {
		page = parseInt(req.body['page']);
	} else if (typeof req.param('page') != 'undefined') {
		page = parseInt(req.param('page'));
	}

	if (typeof page=='undefined' || isNaN(page)) {
		page = 1;
	} else if (page<=0) {
		page = 1;
	}

	if (typeof req.body['word'] != 'undefined') {
		word = decodeURIComponent(req.body['word']).trim();
	} else if (typeof req.param('word') != 'undefined') {
		word = decodeURIComponent(req.param('word')).trim();
	}

	if (word=='') {
		result.ret = -1;
		delete result.data;

		output(req, res, result, jsonpCallback);
	} else {
		fetchList(word, page, function (data) {
			result.data = data;
			output(req, res, result, jsonpCallback);
		});
	}

});

/**
 *	Heroku认为首页打不开时，整个应用就是错误的，So ...
 *
 */
app.all('/', function (req, res) {
	res.send('<h3>'+CONFIG.APP_NAME+'</h3>');
	res.send('<h4>[email]: '+CONFIG.AUTHOR+'</h4>');
});

if (ip) {
	app.listen(port, ip, function () {
		console.log('Proxy listening on '+ip+', port '+port);
	});
} else {
	app.listen(port, function () {
		console.log('Proxy listening on port '+port);
	});
}